package co.edu.usbcali.ai.ga.bl;

import java.util.ArrayList;
import java.util.List;

import co.edu.usbcali.ai.ga.Ga;
import co.edu.usbcali.ai.ga.Gene;
import co.edu.usbcali.ai.ga.Generation;
import co.edu.usbcali.ai.ga.ICromosom;
import co.edu.usbcali.ai.ga.Individual;

import com.cgarias.utils.Random;


public class SimpleMutator implements IMutator {
	
	private static SimpleMutator instance=new SimpleMutator();

	public static SimpleMutator getInstance() {
		return instance;
	}

	@SuppressWarnings("unchecked")
	@Override
	public ICromosom mutate(ICromosom cromosom,Class<? extends ICromosom> cromosomImplementation) throws InstantiationException, IllegalAccessException{
		int cut=Random.random(cromosom.size());
		List<Gene> ls=cromosom.subCromosom(new Integer(0),new Integer(cut));
		List<Gene> rs=cromosom.subCromosom(new Integer(cut+1));
		ICromosom mutatedCromosom=cromosomImplementation.newInstance();
		mutatedCromosom.setType(cromosom.getType());
		Gene gen=cromosom.get(cut);
		Gene mutatedGen=gen.cloneMutating();
		mutatedCromosom.addAll(ls);
		mutatedCromosom.add(mutatedGen);
		mutatedCromosom.addAll(rs);
		return mutatedCromosom;
	}

	@Override
	public List<Individual> mutate(List<Individual> parentsList,
			List<Individual> brothersList, int childrenNumber, int p_generation,Class<? extends ICromosom> cromosomImplementation,Ga ga) throws InstantiationException, IllegalAccessException{
		List<ICromosom> cromosomsList=new ArrayList<ICromosom>(childrenNumber);
		List<ICromosom> cromosomsParentsList=Generation.getCromosomsList(parentsList);
		List<ICromosom> cromosomsBrothersList=Generation.getCromosomsList(brothersList);
		int fatherIndex;
		ICromosom cromosom;
		for (int con=0;con<childrenNumber;con++){
			do{
			fatherIndex=Random.random(parentsList.size());
			ICromosom fatherCromosom=parentsList.get(fatherIndex).getCromosom();
//			System.out.println("P:"+fatherCromosom);
			cromosom=mutate(fatherCromosom,cromosomImplementation);
//			System.out.println("mut:"+cromosom);
			}while (cromosomsParentsList.contains(cromosom)||
					 cromosomsBrothersList.contains(cromosom)||
					 cromosomsList.contains(cromosom));
			cromosomsList.add(cromosom);
		}
		return Generation.createIndividualsList(cromosomsList, p_generation,ga);
	}

}
